dbus 工具

·

学习项目

  • zbus https://github.com/z-galaxy/zbus
  • pydbus https://github.com/LEW21/pydbus
  • python-dbus-next https://github.com/altdesktop/python-dbus-next
  • pystemd https://github.com/systemd/pystemd
  • bluez-test https://github.com/bluez/bluez/tree/master/test
  • Ulauncher https://github.com/Ulauncher/Ulauncher
  • busctl https://github.com/systemd/systemd/tree/main/src/busctl
  • xdg-desktop-portal https://github.com/flatpak/xdg-desktop-portal

GitHub 实战项目(可直接运行/贡献)

system76-scheduler调度器 GUI,用 DBus 控制 systemd/CPUPython + pydbusorg.freedesktop.systemd1, logind
gnome-shell-screenshot类 Flameshot 工具JS + DBusportal.Screenshot, portal.Clipboard
blueman蓝牙管理器(Python)pydbus + GTKorg.bluez, obex 协议
udisks2-wrapper磁盘挂载示例pydbusorg.freedesktop.UDisks2

DBus 工具类

项目描述
d-spyGTK DBus Inspector(看接口/发请求) ✅ 强烈推荐安装
dbus-next纯 Python async DBus 实现(兼容性好)
xdg-desktop-portal官方测试用例(含 Python)→ 学 a{sv} 参数构造
portal-test专测 portal 接口的工具

快速上手:5 个常用服务实战代码

  • 依赖:pip install pydbus(初学)或 pip install zbus(进阶)
  • 1️⃣ 发送桌面通知(org.freedesktop.Notifications)
# notify.py
from pydbus import SessionBus

bus = SessionBus()
notif = bus.get('.Notifications')

# 发送通知
notif.Notify(
    "MyApp",   # app_name
    0,         # replaces_id
    "",        # app_icon
    "标题",    # summary
    "消息内容", # body
    [],        # actions
    {"urgency": 1},  # hints (a{sv})
    5000       # timeout ms
)

✅ 运行:python3 notify.py → 右上角弹出通知

  • 2️⃣ 控制蓝牙开关(org.bluez)
# bluetooth.py
from pydbus import SystemBus

bus = SystemBus()
# 获取默认适配器(如 hci0)
adapter = bus.get('org.bluez', '/org/bluez/hci0')

print("Powered:", adapter.Powered)
adapter.Powered = False  # 关闭蓝牙
# adapter.Powered = True  # 开启

⚠️ 需权限:sudo usermod -aG bluetooth $USER + 重登

  • 3️⃣ 查询电池状态(org.freedesktop.UPower)
# battery.py
from pydbus import SystemBus

bus = SystemBus()
upower = bus.get('org.freedesktop.UPower', '/org/freedesktop/UPower')

for dev_path in upower.EnumerateDevices():
    dev = bus.get('org.freedesktop.UPower', dev_path)
    if dev.Type == 2:  # 2 = Battery
        print(f"电量: {dev.Percentage:.1f}% | 状态: {dev.State}")
  • 4️⃣ 调用截图 portal(解决你的 Flameshot 问题!)
# portal_screenshot.py
from pydbus import SessionBus
import time

bus = SessionBus()
portal = bus.get('org.freedesktop.portal.Desktop',
                 '/org/freedesktop/portal/desktop')

# 创建 Request 对象
request = bus.get('org.freedesktop.portal.Desktop',
                  portal.Request.CreateRequest('', '')[0])

# 触发截图(interactive 模式)
opts = {
    'modal': True,
    'interactive': True
}
portal.Screenshot(request, opts)

# 监听 Response(简化版)
def on_response(response, results):
    if response == 0:  # 0 = success
        print("截图保存路径:", results.get('uri'))
    else:
        print("用户取消或失败")

request.onResponse = on_response
time.sleep(10)  # 等待用户操作

✅ 运行后弹出 GNOME 截图界面 → 标注后保存路径打印到终端

  • 5️⃣ 重启 systemd 用户服务(org.freedesktop.systemd1)
# restart_service.py
from pydbus import SessionBus

bus = SessionBus()
systemd = bus.get('.systemd1')

# 重启 flameshot 服务(若配置了 autostart)
systemd.RestartUnit('flameshot.service', 'replace')
print("Flameshot 服务已重启")

调试技巧(结合你之前的环境)

  • 快速定位 portal 问题:
# 1. 监控 portal 通信
busctl --session monitor --match="interface='org.freedesktop.portal.*'"

# 2. 检查 polkit 规则
pkaction --verbose --action-id org.freedesktop.portal.desktop.screenshot

# 3. 手动测试权限
gdbus call --session \
  --dest org.freedesktop.portal.Desktop \
  --object-path /org/freedesktop/portal/desktop \